#ifndef __ITKEXT__IMAGE__IMAGEMOMENTS__H__
#define __ITKEXT__IMAGE__IMAGEMOMENTS__H__

#include <itkFunctionBase.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkMatrix.h>
#include <itkSpatialObject.h>

#include <itkExtMomentsCalculator.h>

namespace itkExt
{
  /**
   */
  template< class I, class S = double, class M = I >
  class ImageMoments
    : public itk::Object
  {
  public:
    typedef ImageMoments                    Self;
    typedef itk::Object                     Superclass;
    typedef itk::SmartPointer< Self >       Pointer;
    typedef itk::SmartPointer< const Self > ConstPointer;

    itkStaticConstMacro( Dimension, unsigned int, I::ImageDimension );

    typedef I                           TImage;
    typedef S                           TScalar;
    typedef M                           TImageMask;
    typedef typename TImage::IndexType  TIndex;
    typedef typename TImage::PixelType  TPixel;
    typedef typename TImage::RegionType TRegion;

    typedef itkExt::MomentsCalculator< TScalar, Dimension > TCalculator;
    typedef typename TCalculator::THMatrix                  THMatrix;
    typedef typename TCalculator::TMatrix                   TMatrix;
    typedef typename TCalculator::TPoint                    TPoint;
    typedef typename TCalculator::TVector                   TVector;

    typedef itk::SpatialObject< Dimension >     TSpatialObject;
    typedef itk::FunctionBase< TPixel, TPixel > TPixelFunction; 

  protected:
    typedef itk::ImageRegionConstIteratorWithIndex< TImage > _TIterator;

  public:
    itkNewMacro( Self );
    itkTypeMacro( ImageMoments, itkObject );

    itkGetConstObjectMacro( Image, TImage );
    itkGetConstObjectMacro( ImageMask, TImageMask );
    itkGetConstObjectMacro( SpatialMask, TSpatialObject );
    itkGetObjectMacro( PixelFunction, TPixelFunction );

    itkSetConstObjectMacro( Image, TImage );
    itkSetConstObjectMacro( ImageMask, TImageMask );
    itkSetConstObjectMacro( SpatialMask, TSpatialObject );;
    itkSetObjectMacro( PixelFunction, TPixelFunction );

  public:
    const TScalar& GetMass( ) const
      { return( this->m_Calculator.GetMass( ) ); }
    const TVector& GetCenter( ) const
      { return( this->m_Calculator.GetCenter( ) ); }
    const TVector& GetOffset( ) const
      { return( this->m_Calculator.GetOffset( ) ); }
    const TMatrix& GetInertia( ) const
      { return( this->m_Calculator.GetInertia( ) ); }
    const TVector& GetProperValues( ) const
      { return( this->m_Calculator.GetProperValues( ) ); }
    const TMatrix& GetProperMatrix( ) const
      { return( this->m_Calculator.GetProperMatrix( ) ); }
    THMatrix GetHomogeneousMatrix( ) const
      { return( this->m_Calculator.GetHomogeneousMatrix( ) ); }

    void AlignProperMatrix( const TVector& dir )
      { this->m_Calculator.AlignProperMatrix( dir ); }
    void AlignProperMatrix( const TMatrix& rot )
      { this->m_Calculator.AlignProperMatrix( rot ); }

    virtual void Compute( )
      { this->Compute( this->m_Image->GetRequestedRegion( ) ); }
    virtual void Compute( const TRegion& reg );

  protected:
    ImageMoments( );
    virtual ~ImageMoments( );

    bool _ComputeValue( TPixel& v, TVector& p, const _TIterator& i ) const;

  private:
    ImageMoments( const Self& );   // Not impl.
    void operator=( const Self& ); // Not impl.

  protected:
    TCalculator m_Calculator;

    typename TImage::ConstPointer         m_Image;
    typename TImageMask::ConstPointer     m_ImageMask;
    typename TSpatialObject::ConstPointer m_SpatialMask;
    typename TPixelFunction::Pointer      m_PixelFunction;
  };

} // ecapseman

#include <itkExtImageMoments.txx>

#endif // __ITKEXT__IMAGE__IMAGEMOMENTS__H__

// eof - $RCSfile: itkExtImageMoments.h,v $
